import axios from "axios";

const CancelToken = axios.CancelToken;

// 常量 缓存的过期时间 毫秒单位
const EXPIRED_TIME = 5 * 1000;
// 缓存的列表 只针对缓存列表里面的地址进行缓存
export const cacheList = ["/product/id/"];
// 声明 使用轮询的方式 清理缓存 间隔一段时间就清理掉不经常访问的缓存
const CLEAR_CACHE_INTERVAL = 2000;
// 设置缓存最大长度 当新写入缓存时，超出了最大长度，就把超出数量的并且最接近过期的缓存给删掉
const MAX_CACHE_NUMBER = 5;

const ApiCache = new Map();

const expires = new Map();

// 作用：设置缓存的过期时间
export function setExpires(key) {
  expires.set(key, Date.now() + EXPIRED_TIME);
}

// 设置对应的 api 缓存
export function setApiCache(url, data, params = {}) {
  if (!cacheList.includes(url)) return;

  const key = url + JSON.stringify(params);
  console.log(key + "新设置缓存");

  ApiCache.set(key, data);

  setExpires(key);

  outRangeCache();
}

// 从缓存的map里面判断 传一个key判断有没有 相应的对象存在，有则返回true 没有就返回false
export function hasApiCache(url, params = {}) {
  const key = url + JSON.stringify(params);
  if (!ApiCache.has(key)) return false;
  // return ApiCache.has(key);
  //  检查对应的缓存数据有没有过期
  if (expires.get(key) <= Date.now()) {
    console.log(key + "缓存已经过期");
    deleteApiCache(key);
    return false;
  }

  return true;
}

// 从缓存的map里面获取 缓存
export function getApiCache(url, params = {}) {
  const key = url + JSON.stringify(params);
  setExpires(key);
  return ApiCache.get(key);
}
// 删除缓存
export function deleteApiCache(key) {
  ApiCache.delete(key);
  expires.delete(key);
}
// 1.轮询方式清理缓存
export function clearCache() {
  for (let [key, timestamp] of expires) {
    if (timestamp <= Date.now()) {
      deleteApiCache(key);
      console.log(key + "缓存已清理");
    }
  }
}
// 2.间歇定时器
// eslint-disable-next-line no-unused-vars
const timer = setInterval(clearCache, CLEAR_CACHE_INTERVAL);

// 通过缓存的最大长度控制缓存
export function outRangeCache() {
  const number = expires.size - MAX_CACHE_NUMBER;
  if (number > 0) {
    console.log("超出缓存数量");
    [...expires.entries()]
      .sort((a, b) => a[1] - b[1])
      .slice(0, number)
      .forEach(([key]) => deleteApiCache(key));
  }
}

// 返回一个cancel函数 只要调用返回的结果 就能取消此次请求
export function addCancelConfig(url, config) {
  if (!cacheList.includes(url)) return;
  let cancel = null;
  config.cancelToken = new CancelToken((c) => (cancel = c));
  return cancel;
}

{
  //    取消请求 示例
  //     const CancelToken = axios.CancelToken;
  //     let cancel;
  //
  //     axios.get('/user/12345', {
  //         cancelToken: new CancelToken(function executor(c) {
  //             // executor 函数接收一个 cancel 函数作为参数
  //             cancel = c;
  //         })
  //     });
  // // cancel the request
  //     cancel();
}
